package cn.bigfire.wzdj.util;

import cn.hutool.core.lang.Console;
import cn.hutool.core.util.HexUtil;
import cn.hutool.core.util.StrUtil;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import io.netty.buffer.ByteBufUtil;
import io.netty.util.internal.StringUtil;
import lombok.extern.slf4j.Slf4j;

import java.util.Base64;

/**
 * 字节码 格式化 工具类
 * 逆向中 大多操作byte数据 此工具类用于,数据的转换。
 *
 * 内容包括:
 * 1.不同类型的字符串转换。
 * 2.字符串到byte[]的转换。
 * 3.从字节中获取bit信息等方法。
 * 4.byte数据打印相关
 */
@Slf4j
public class ByteUtil {


    //1.不同类型的字符串转换。
    /**
     * 字符串转byte[]  web 数据  ->  hex 数据转换
     *
     * @param webStr 字符串
     * @return byte[]
     */
    public static String web2hex(String webStr){
        String replace = webStr.replace(" ", "-").replace("\n", "-");
        StringBuilder stringBuilder = new StringBuilder();
        String[] split = replace.split("-");
        for (String four : split) {
            if (four.length() == 4) {
                String[] split1 = StrUtil.split(four, 2);
                String nS = split1[0];
                if (split1.length == 2) {
                    nS = split1[0] + "-" + split1[1];
                }
                stringBuilder.append(nS).append("-");
            } else {
                stringBuilder.append(four).append("-");
            }
        }
        String end = stringBuilder.toString();
        if (StrUtil.endWith(end, "-")) {
            end = end.substring(0, end.length() - 1);
        }
        return end;
    }


    //2.字符串到byte[]的转换。
    /**
     * 字符串转byte[]  wireshark fiddler 十六进制数据
     *
     * @param hexStr 字符串
     * @return byte[]
     */
    public static byte[] hex2bytes(String hexStr) {
        return HexUtil.decodeHex(hexStr.replace("-", ""));
    }

    /**
     * 字符串转byte[]  web 数据  0100 4000 1c00 0a00 0000 0000
     *
     * @param webStr 字符串
     * @return byte[]
     */
    public static byte[] web2bytes(String webStr) {
        String hex = web2hex(webStr);
        return hex2bytes(hex);
    }

    /**
     * 字符串转byte[]  base64 数据
     *
     * @param base64Str 字符串
     * @return byte[]
     */
    public static byte[] base64bytes(String base64Str) {
        //AQAQAIysG2c=
        return Base64.getDecoder().decode(base64Str);
    }


    //3.从字节中获取bit信息等方法。

    /**
     * 字符串转byte[]  并打印 hex 数据矩阵
     *
     * @param str 字符串
     */
    public static void log(String str) {
        try {
            log(str.getBytes("UTF-8"));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * byte[]  打印 hex 数据矩阵
     *
     * @param bytes 字节数组
     */
    public static void log(byte[] bytes) {
        ByteBuf byteBuf = ByteBufAllocator.DEFAULT.buffer();
        byteBuf.writeBytes(bytes);
        log(byteBuf);
    }

    /**
     * byteBuf  打印 hex 数据矩阵
     *
     * @param byteBuf byteBuf对象
     */
    public static void log(ByteBuf byteBuf) {
        StringBuilder dump = new StringBuilder();
        dump.append("read index:").append(byteBuf.readerIndex()).append("\t");
        dump.append("write index:").append(byteBuf.writerIndex()).append("\t");
        dump.append("capacity index:").append(byteBuf.capacity()).append(StringUtil.NEWLINE);
        ByteBufUtil.appendPrettyHexDump(dump, byteBuf);
        log.info(dump.toString());
    }

    /**
     * byteBuf  打印 hex 数据矩阵
     *
     * @param byteBuf byteBuf对象
     * @param in 是否为进入数据 (带个><剪头而已)
     */
    public static void log(ByteBuf byteBuf, boolean in) {
        StringBuilder dump = new StringBuilder();
        dump.append("read index:").append(byteBuf.readerIndex()).append("\t");
        dump.append("write index:").append(byteBuf.writerIndex()).append("\t");
        dump.append("capacity index:").append(byteBuf.capacity()).append(StringUtil.NEWLINE);
        ByteBufUtil.appendPrettyHexDump(dump, byteBuf);
        String str = dump.toString().replace("+", in ? "<" : ">");
        log.info(str);
    }

    /**
     * 根据字节(K)长度，  自动转为KB,MB,GB表示 并返回字符串
     *
     * @param len 字节长度
     * @return  String 数据大小
     */
    public static String getSize(long len) {
        int byteNum = 1024;
        if (len < byteNum) {
            return len + "B";
        } else if (len < Math.pow(byteNum, 2)) {
            return String.format("%.2fKB", len / Math.pow(byteNum, 1));
        } else if (len < Math.pow(byteNum, 3)) {
            return String.format("%.2fMB", len / Math.pow(byteNum, 2));
        } else {
            return String.format("%.2fGB", len / Math.pow(byteNum, 3));
        }
    }

    /**
     * 根据字节(K)长度，  自动转为KB,MB,GB表示 并打印
     *
     * @param len 字节长度
     */
    public static void printSize(long len) {
        log.info(getSize(len));
    }

    /**
     * 获取to之前  (获取 byte[] 从0到to的小字节数组)
     *
     * @param bytes 原字节数组
     * @param to 结束位置
     */
    public static byte[] subBefore(byte[] bytes, int to) {
        byte[] before = new byte[to];
        if (bytes.length < (to)) {
            System.arraycopy(bytes, 0, before, 0, bytes.length);
        } else {
            System.arraycopy(bytes, 0, before, 0, to);
        }
        return before;
    }

    /**
     * 获取from之后 (获取 byte[] 从from到结束的小字节数组)
     *
     * @param bytes 原字节数组
     * @param form 开始位置
     */
    public static byte[] subAfter(byte[] bytes, int form) {
        byte[] after = new byte[bytes.length - form];
        System.arraycopy(bytes, form, after, 0, bytes.length - form);
        return after;
    }

    /**
     * 获取from之后to之前 (获取 byte[] 从from到to的小字节数组)
     *
     * @param bytes 原字节数组
     * @param form 开始位置
     * @param to 结束位置
     */
    public static byte[] subBetween(byte[] bytes, int form, int to) {
        try {
            int len = to - form;
            byte[] between = new byte[len];
            if (len <= bytes.length) {
                System.arraycopy(bytes, form, between, 0, len);
            } else {
                System.err.printf("form:%s,to:%s,data.size:%s%n", form, to, bytes.length);
                for (int i = 1; i < 5; i++) {
                    System.err.println(cn.bigfire.wzdj.util.Console.where(i) + "位置" + i);
                }
//                return new byte[0];
            }
            return between;
        } catch (Exception e) {
            System.err.printf("form:%s,to:%s,data.size:%s%n", form, to, bytes.length);
//            e.printStackTrace();
//            System.exit(0);
        }
        return new byte[0];
    }


    /**
     * 可以理解为 或 运算 加密运行一次，解密再运行一次就行了
     *
     * @param data 原数据
     * @param mask mask websocket服务器随机生成的32位4字节的掩码
     * @return byte[]  掩码后
     */
    public static byte[] XOR(byte[] data, byte[] mask) {
        byte[] xorResult = new byte[Math.max(data.length, mask.length)];
        for (int i = 0; i < xorResult.length; i++) {
            if (i < data.length) {
                xorResult[i] = (byte) (data[i] ^ mask[i]);
            }
        }
        return xorResult;
    }



}
